package cn.south.campus.admin.sys.service.impl;

import cn.south.campus.admin.sys.mapper.SysMenuMapper;
import cn.south.campus.admin.sys.model.entity.SysMenu;
import cn.south.campus.admin.sys.model.enums.SysRespEnums;
import cn.south.campus.admin.sys.model.req.SysMenuReq;
import cn.south.campus.admin.sys.model.vo.SysMenuVo;
import cn.south.campus.admin.sys.model.vo.SysUserMenuVo;
import cn.south.campus.admin.sys.service.SysMenuService;
import cn.south.campus.common.model.enums.CommonEnums;
import cn.south.campus.common.utils.AssertUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 实现层
 *
 * @author chow
 * @since 2024-11-01 16:26:54
 **/
@Service
@AllArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private final SysMenuMapper sysMenuMapper;

    @Override
    public IPage<SysMenuVo> page(SysMenuReq query) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<SysMenu>().like(StringUtils.isNotBlank(query.getMenuName()), SysMenu::getMenuName, query.getMenuName());
        Page<SysMenu> sysMenuPage = sysMenuMapper.selectPage(query.getPageDto(), wrapper);
        return sysMenuPage.convert(SysMenuVo::convert);
    }

    @Override
    public List<SysMenuVo> list(SysMenuReq query) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<SysMenu>().like(StringUtils.isNotBlank(query.getMenuName()), SysMenu::getMenuName, query.getMenuName());
        List<SysMenu> sysMenuList = sysMenuMapper.selectList(wrapper);
        return buildMenus(sysMenuList, 0L, query.getMenuName());
    }

    @Override
    public List<String> findPermission(Long roleId) {
        return sysMenuMapper.selectPermissions(roleId);
    }

    @Override
    public SysMenuVo detail(Long id) {
        SysMenu sysMenu = sysMenuMapper.selectById(id);
        return SysMenuVo.convert(sysMenu);
    }

    @Override
    public void add(SysMenuVo vo) {
        SysMenu sysMenu = SysMenuVo.convert(vo);
        sysMenuMapper.insert(sysMenu);
    }

    @Override
    public void delete(Long id) {
        //查询该菜单下面是否还有菜单
        SysMenu sysMenu = getById(id);
        AssertUtils.isNotNull(sysMenu, CommonEnums.DATA_HAS_NOT_ERROR);
        if (sysMenu.getParentId().equals(BigDecimal.ZERO.longValue())) {
            //查询该父级菜单下还有没有子菜单
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id);
            List<SysMenu> list = sysMenuMapper.selectList(wrapper);
            AssertUtils.isNotBlankCollection(list, SysRespEnums.MENU_HAS_CHILD_ERROR);
        }
        sysMenuMapper.deleteById(id);
    }

    @Override
    public void updateMenu(SysMenuVo vo) {
        SysMenu sysMenu = getById(vo.getId());
        AssertUtils.isNotNull(sysMenu, CommonEnums.DATA_HAS_NOT_ERROR);
        sysMenu.setMenuName(vo.getMenuName());
        sysMenu.setPath(vo.getPath());
        sysMenu.setParentId(vo.getParentId());
        sysMenu.setIcon(vo.getIcon());
        sysMenu.setPermissionCode(vo.getPermissionCode());
        sysMenu.setSort(vo.getSort());
        sysMenuMapper.updateById(sysMenu);
    }

    @Override
    public List<SysUserMenuVo> findMenuRole(Long roleId) {
        //查询所有菜单列表
        List<SysMenu> menuList = sysMenuMapper.selectMenusRoleId(roleId);
        //递归构建菜单属性结构
        return recursionMenu(0L, menuList);
    }

    @Override
    public boolean isExistChildren(Long id) {
        SysMenu adminMenu = sysMenuMapper.selectOne(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, id)
                .last("limit 1"));
        return adminMenu != null;
    }

    /**
     * 递归菜单集合
     *
     * @param parentId 父级ID
     * @param menus    菜单集合
     * @return 树形结构的菜单
     */
    private List<SysMenuVo> buildMenus(List<SysMenu> menus, Long parentId, String menuName) {
        //搜索条件
        if (StringUtils.isNotEmpty(menuName)) {
            for (SysMenu menu : menus) {
                if (menu.getParentId().equals(parentId)) {
                    return menus.stream().map(x -> getSysMenuListVo(parentId, x)).collect(Collectors.toList());
                }
            }
            return menus.stream().filter(sysMenu -> !sysMenu.getParentId().equals(parentId)).
                    map(x -> getSysMenuListVo(parentId, x)).collect(Collectors.toList());
        }
        //遍历所有菜单 找出所有父级菜单
        List<SysMenuVo> list = menus.stream().
                filter(sysMenu -> sysMenu.getParentId().equals(parentId)).
                map(x -> getSysMenuListVo(parentId, x)).collect(Collectors.toList());
        //遍历父级菜单
        for (SysMenuVo parentMenus : list) {
            List<SysMenuVo> sysMenuListVos = buildMenus(menus, parentMenus.getId(), menuName);
            if (sysMenuListVos.size() > 0) {
                //将子菜单加入到父级菜单下面
                parentMenus.setChildren(sysMenuListVos);
            }
        }
        return list;
    }

    private SysMenuVo getSysMenuListVo(Long parentId, SysMenu x) {
        SysMenuVo sysMenuVo = new SysMenuVo();
        sysMenuVo.setIcon(x.getIcon());
        sysMenuVo.setMenuName(x.getMenuName());
        sysMenuVo.setPath(x.getPath());
        sysMenuVo.setPermissionCode(x.getPermissionCode());
        sysMenuVo.setId(x.getId());
        sysMenuVo.setParentId(parentId);
        return sysMenuVo;
    }

    /**
     * 递归遍历菜单集合
     *
     * @param parentId 父级ID
     * @param menuList 菜单集合
     * @return List<SysUserMenuVo>
     */
    private List<SysUserMenuVo> recursionMenu(Long parentId, List<SysMenu> menuList) {
        List<SysUserMenuVo> sysUserMenuVos = new ArrayList<>();
        //查询父级菜单  遍历所有菜单
        for (SysMenu sysMenu : menuList) {
            if (sysMenu.getParentId().equals(parentId)) {
                SysUserMenuVo sysUserMenuVo = new SysUserMenuVo();
                sysUserMenuVo.setIcon(sysMenu.getIcon());
                sysUserMenuVo.setId(sysMenu.getId());
                sysUserMenuVo.setPath(sysMenu.getPath());
                sysUserMenuVo.setMenuName(sysMenu.getMenuName());
                sysUserMenuVos.add(sysUserMenuVo);
            }
        }
        //遍历父级菜单
        for (SysUserMenuVo sysUserMenuVo : sysUserMenuVos) {
            List<SysUserMenuVo> chirdenList = recursionMenu(sysUserMenuVo.getId(), menuList);
            if (chirdenList.size() > 0) {
                sysUserMenuVo.setChildren(chirdenList);
            }
        }
        return sysUserMenuVos;
    }

}
